package coroutines

import kotlinx.coroutines.*
import java.io.File
import kotlin.concurrent.thread

private fun letUsPrintln(msg : String){
    println("$msg Thread_name：${Thread.currentThread().name}")
}

suspend fun main(args: Array<String>) {

//    coroutines_lauch()
//    coroutines_runBlocking()
//    testScope()
//    testAsync()

//    val job = GlobalScope.launch{
//        val files = getAllFiles("C:/").await()
//        files?.forEach{
//            println(it.absolutePath)
//        }
//    }
//    job.join()
//    testChildCorutin()
//    testCoroutineScope()
    runBlocking {
        hello()
        println("Done")
        withTimeout(1200){
            
        }
    }
}

suspend fun hello() = coroutineScope {
    launch {
        delay(2000L)
        println("World2!")
    }
    launch {
        delay(1000L)
        println("World1!")
    }
    println("Hello")
}

fun testChildCorutin(){
    runBlocking {
        launch {
            letUsPrintln("World")
            delay(1000L)
            letUsPrintln("end!")
        }
        letUsPrintln("Hello,")
    }
}

fun testCoroutineScope(){
    runBlocking {
        launch {
            delay(200L)
            letUsPrintln("Task from runblocking")
        }
        coroutineScope {
            launch {
                delay(500L)
                letUsPrintln("Task from nested launch")
            }
            delay(100L)
            letUsPrintln("Task from coroutine scope")
        }
        letUsPrintln("Coroutine scope is over")
    }
}

fun coroutines_runBlocking() {

    runBlocking(Dispatchers.IO) {
        delay(1000)
        println("hello")
    }
    println("world")
}

private fun coroutines_lauch() {
    GlobalScope.launch {
        delay(1000L)
        println("world")
    }
    println("hello")
    Thread.sleep(2000)
}

private fun testScope(){
    runBlocking {
        val job = launch {
            GlobalScope.launch {
                for (i in 0..9){
                    println("GlobalScope thread = ${Thread.currentThread().name} -> $i")
                    delay(100)
                }
            }

            launch {
                for (i in 0..9){
                    println("Normal thread = ${Thread.currentThread().name} -> $i")
                    delay(100)
                }
            }
        }

        delay(300)
        job.cancel()
        delay(500)
    }
}

suspend fun getAllFiles(path : String, regax : String = "^.+$") : Deferred<MutableList<File>?>{
    return coroutineScope {
        async {
            val files = File(path).listFiles { file ->
                val n = file.absolutePath
                n.matches(Regex(regax))
            }
            files?.toMutableList()
        }
    }
}

private fun testAsync(){

    runBlocking {

        val job1 = async {

            for (i in 0..9){
                delay(100)
            }
            10
        }
        val job2 = async {
            for (i in 0..5){
                delay(100)
            }
            20
        }
        println("10 + 20 = ${job1.await() + job2.await()}")
    }
}
